using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using NBiDi.Extensions;
using SilverlightToolbox;

namespace SilverlightToolbox.RTL
{
    public static class SilverlightAlignmenetParagraphsToRowsAlgorithem
    {
        public static List<TextBlock> RtlTextBlockToWrappingScenarios(TextBlock textBlockToRTL, bool ForceAllParagraphsAsRTL)
        {
            List<TextBlock> TextBlocksAttachedToCanvas = new List<TextBlock>();
            Canvas ParentOfTextBlockToRTL = (Canvas)textBlockToRTL.Parent;
            double curHeightOffsetForBreakLines = 0;
            string lastLineText = string.Empty;
            foreach (string curParagraph in NBiDiExtensions.SplitToParagraphs(textBlockToRTL.Text))
            {
                if (!string.IsNullOrEmpty(curParagraph))
                {
                    curHeightOffsetForBreakLines = SplitParagraphIntoLinesWithNoBrokenWordsNoBrokwnNumbersCorrectWrappingAndCorrectPlacemenetOnScreen(textBlockToRTL, ParentOfTextBlockToRTL, curHeightOffsetForBreakLines, curParagraph, ForceAllParagraphsAsRTL, TextBlocksAttachedToCanvas, lastLineText);
                }
                else
                {
                    curHeightOffsetForBreakLines = AddEmptyLine(textBlockToRTL, ForceAllParagraphsAsRTL, TextBlocksAttachedToCanvas, curHeightOffsetForBreakLines, curParagraph, lastLineText);
                }
            }
            ParentOfTextBlockToRTL.Children.Remove(textBlockToRTL);

            return TextBlocksAttachedToCanvas;
        }

        private static double AddEmptyLine(TextBlock textBlockToRTL, bool ForceAllParagraphsAsRTL, List<TextBlock> TextBlocksAttachedToCanvas, double curHeightOffsetForBreakLines, string curParagraph, string lastLineText)
        {
            double textBlockToRTLCanvasTop = (double)textBlockToRTL.GetValue(Canvas.TopProperty);
            double textBlockToRTLCanvasLeft = (double)textBlockToRTL.GetValue(Canvas.LeftProperty);
            TextBlock newTextBlockForEmptyLine = InitlizeNewTextBlock(textBlockToRTL, curHeightOffsetForBreakLines, curParagraph, textBlockToRTLCanvasTop, new List<char>(new char[] { ' ', ' ' }), ForceAllParagraphsAsRTL, lastLineText);
            curHeightOffsetForBreakLines += newTextBlockForEmptyLine.ActualHeight;
            TextBlocksAttachedToCanvas.Add(newTextBlockForEmptyLine);
            return curHeightOffsetForBreakLines;
        }

        private static double SplitParagraphIntoLinesWithNoBrokenWordsNoBrokwnNumbersCorrectWrappingAndCorrectPlacemenetOnScreen(TextBlock textBlockToRTL, Canvas ParentOfTextBlockToRTL, double curHeightOffsetForBreakLines, string curParagraph, bool ForceAllParagraphsAsRTL, List<TextBlock> TextBlocksAttachedToCanvas, string lastLineText)
        {
            double textBlockToRTLCanvasTop = (double)textBlockToRTL.GetValue(Canvas.TopProperty);
            double textBlockToRTLCanvasLeft = (double)textBlockToRTL.GetValue(Canvas.LeftProperty);

            List<char> queueOfCharsInStringToBeAdded = new List<char>(curParagraph.ToCharArray());

            TextBlock newTextBlockForOneLineOnly = InitlizeNewTextBlock(textBlockToRTL, curHeightOffsetForBreakLines, curParagraph, textBlockToRTLCanvasTop, queueOfCharsInStringToBeAdded, ForceAllParagraphsAsRTL, lastLineText);

            while (IsNotQueueEmpty(queueOfCharsInStringToBeAdded))
            {
                IterateOverAllRemainingLettersNotOnScreenPutThemInLinesWithCorrectSyntax(textBlockToRTL, ParentOfTextBlockToRTL, ref curHeightOffsetForBreakLines, curParagraph, textBlockToRTLCanvasTop, textBlockToRTLCanvasLeft, queueOfCharsInStringToBeAdded, ref newTextBlockForOneLineOnly, ForceAllParagraphsAsRTL, TextBlocksAttachedToCanvas, ref lastLineText);
            }

            curHeightOffsetForBreakLines = AttachNewTextBlockAfterFinishedDeterminingItsText(textBlockToRTL, ParentOfTextBlockToRTL, curHeightOffsetForBreakLines, curParagraph, textBlockToRTLCanvasLeft, newTextBlockForOneLineOnly, ForceAllParagraphsAsRTL, TextBlocksAttachedToCanvas, lastLineText);
            return curHeightOffsetForBreakLines;
        }

        private static void IterateOverAllRemainingLettersNotOnScreenPutThemInLinesWithCorrectSyntax(TextBlock textBlockToRTL, Canvas ParentOfTextBlockToRTL, ref double curHeightOffsetForBreakLines, string curParagraph, double textBlockToRTLCanvasTop, double textBlockToRTLCanvasLeft, List<char> queueOfCharsInStringToBeAdded, ref TextBlock newTextBlockForOneLineOnly, bool ForceAllParagraphsAsRTL, List<TextBlock> TextBlocksAttachedToCanvas, ref string lastLineText)
        {
            double actualHeightOfNewTextBlockBegingingIteration = newTextBlockForOneLineOnly.ActualHeight;

            newTextBlockForOneLineOnly.Text += GetFirstAndRemoveIt(queueOfCharsInStringToBeAdded);

            if ((IsNotQueueEmpty(queueOfCharsInStringToBeAdded)) &&
                actualHeightOfNewTextBlockBegingingIteration != newTextBlockForOneLineOnly.ActualHeight)
            {
                RemoveLastCharFromTextBlockAndReturnToQueue(queueOfCharsInStringToBeAdded, newTextBlockForOneLineOnly);

                string textBeforeWholeHandle = newTextBlockForOneLineOnly.Text;


                HandleAllByMovingUntilWhitespace(textBlockToRTL, queueOfCharsInStringToBeAdded, newTextBlockForOneLineOnly);
                ShrinkDownWrapWithOverflowToOneLine(actualHeightOfNewTextBlockBegingingIteration,
                                                    queueOfCharsInStringToBeAdded, newTextBlockForOneLineOnly);

                //HandleWithBrokwnWords(textBlockToRTL, queueOfCharsInStringToBeAdded, newTextBlockForOneLineOnly);

                //HandleWithBrokenNumbersAndMoveSpacersToTextBlock(textBlockToRTL, queueOfCharsInStringToBeAdded, newTextBlockForOneLineOnly);

                CheckIfWrapLeftEmptyTextBlock_BecauseOfLongWord_AndIfSoRestoreOriginalValue(queueOfCharsInStringToBeAdded, newTextBlockForOneLineOnly, textBeforeWholeHandle);

                if (IsNotQueueEmpty(queueOfCharsInStringToBeAdded))
                {
                    string valueBeforeBiDi = newTextBlockForOneLineOnly.Text;

                    curHeightOffsetForBreakLines = AttachNewTextBlockAfterFinishedDeterminingItsText(textBlockToRTL, ParentOfTextBlockToRTL, curHeightOffsetForBreakLines, curParagraph, textBlockToRTLCanvasLeft, newTextBlockForOneLineOnly, ForceAllParagraphsAsRTL, TextBlocksAttachedToCanvas, lastLineText);
                    lastLineText = valueBeforeBiDi;

                    newTextBlockForOneLineOnly = InitlizeNewTextBlock(textBlockToRTL, curHeightOffsetForBreakLines, curParagraph, textBlockToRTLCanvasTop, queueOfCharsInStringToBeAdded, ForceAllParagraphsAsRTL, lastLineText);
                }
            }
        }

        private static void ShrinkDownWrapWithOverflowToOneLine(double actualHeightOfNewTextBlockBegingingIteration, List<char> queueOfCharsInStringToBeAdded, TextBlock newTextBlockForOneLineOnly)
        {
            while (newTextBlockForOneLineOnly.ActualHeight != actualHeightOfNewTextBlockBegingingIteration)
            {
                newTextBlockForOneLineOnly.Width++;
                newTextBlockForOneLineOnly.TextWrapping = newTextBlockForOneLineOnly.TextWrapping;
            }
        }

        private static void HandleAllByMovingUntilWhitespace(TextBlock textBlockToRTL, List<char> queueOfCharsInStringToBeAdded, TextBlock newTextBlockForOneLineOnly)
        {
            if (textBlockToRTL.TextWrapping == TextWrapping.WrapWithOverflow)
            {
                if (!NBiDiExtensions.IsWhitespace(GetLastCharInTextBlock(newTextBlockForOneLineOnly)))
                    while (IsNotQueueEmpty(queueOfCharsInStringToBeAdded)
                           && !NBiDiExtensions.IsWhitespace(Peek(queueOfCharsInStringToBeAdded)))
                    {
                        newTextBlockForOneLineOnly.Text += GetFirstAndRemoveIt(queueOfCharsInStringToBeAdded);
                    }

                while (IsNotQueueEmpty(queueOfCharsInStringToBeAdded)
                       && NBiDiExtensions.IsWhitespace(Peek(queueOfCharsInStringToBeAdded)))
                    newTextBlockForOneLineOnly.Text += GetFirstAndRemoveIt(queueOfCharsInStringToBeAdded);
            }
            else if (textBlockToRTL.TextWrapping == TextWrapping.Wrap)
            {
                while (newTextBlockForOneLineOnly.Text.Length != 0
                       && !NBiDiExtensions.IsWhitespace(GetLastCharInTextBlock(newTextBlockForOneLineOnly)))
                {
                    RemoveLastCharFromTextBlockAndReturnToQueue(queueOfCharsInStringToBeAdded, newTextBlockForOneLineOnly);
                }
            }
        }

        private static string RemoveFirstCharcter(string text)
        {
            return text.Remove(0, 1);
        }

        private static string RemoveFirstCharcterIfRLOorLRO(string text, ref char? firstCharRemoved)
        {
            if (NBiDiExtensions.LTRFirstCharMark == text[0]
                || NBiDiExtensions.RTLFirstCharMark == text[0])
            {
                firstCharRemoved = text[0];
                return text.Remove(0, 1);
            }
            else
                return text;
        }

        private static bool IsNotQueueEmpty(List<char> queueOfCharsInStringToBeAdded)
        {
            return queueOfCharsInStringToBeAdded.Count != 0;
        }

        private static void CheckIfWrapLeftEmptyTextBlock_BecauseOfLongWord_AndIfSoRestoreOriginalValue(List<char> queueOfCharsInStringToBeAdded, TextBlock newTextBlockForOneLineOnly, string textBeforeWholeHandle)
        {
            if (IsTextBlockEmpty(newTextBlockForOneLineOnly))
            {
                while (newTextBlockForOneLineOnly.Text != textBeforeWholeHandle)
                {
                    newTextBlockForOneLineOnly.Text +=
                        GetFirstAndRemoveIt(queueOfCharsInStringToBeAdded);
                }
            }
        }

        private static bool IsTextBlockEmpty(TextBlock newTextBlockForOneLineOnly)
        {
            return !IsNotTextBlockEmpty(newTextBlockForOneLineOnly);
        }

        private static bool IsNotTextBlockEmpty(TextBlock newTextBlockForOneLineOnly)
        {
            return newTextBlockForOneLineOnly.Text.Length != 0;
        }

        private static void HandleWithBrokenNumbersAndMoveSpacersToTextBlock(TextBlock textBlockToRTL, List<char> queueOfCharsInStringToBeAdded, TextBlock newTextBlockForOneLineOnly)
        {
            if (textBlockToRTL.TextWrapping == TextWrapping.WrapWithOverflow)
                while (true && IsNotQueueEmpty(queueOfCharsInStringToBeAdded))
                {
                    bool AdjustmentsMade = false;

                    //AdjustmentsMade = GetlAllSpacerFromQueueToTextBlock(queueOfCharsInStringToBeAdded, newTextBlockForOneLineOnly, AdjustmentsMade);
                    //AdjustmentsMade = GetNumbersAfterPunctioationOrNumbersFromQueueToTextBlock(queueOfCharsInStringToBeAdded, newTextBlockForOneLineOnly, AdjustmentsMade);
                    //AdjustmentsMade = GetrPunctioationAfterNumbersFromQueueToTextBlock(queueOfCharsInStringToBeAdded, newTextBlockForOneLineOnly, AdjustmentsMade);

                    if (!AdjustmentsMade)
                        break;
                }
            else if (textBlockToRTL.TextWrapping == TextWrapping.Wrap)
                while (true && newTextBlockForOneLineOnly.Text.Length != 0)
                {
                    bool AdjustmentsMade = false;

                    //AdjustmentsMade = ReturnNumbersAfterPunctioationOrNumbersFromTextBlockToQueue(queueOfCharsInStringToBeAdded, newTextBlockForOneLineOnly, AdjustmentsMade);
                    //AdjustmentsMade = ReturnPunctioationAfterNumbersFromTextBlockToQueue(queueOfCharsInStringToBeAdded, newTextBlockForOneLineOnly, AdjustmentsMade);

                    if (!AdjustmentsMade)
                        break;
                }
        }

        private static bool ReturnPunctioationAfterNumbersFromTextBlockToQueue(List<char> queueOfCharsInStringToBeAdded, TextBlock newTextBlockForOneLineOnly, bool AdjustmentsMade)
        {
            while (newTextBlockForOneLineOnly.Text.Length != 0
                   && NBiDiExtensions.IsNumberCharcter(GetLastCharInTextBlock(newTextBlockForOneLineOnly))
                   && NBiDiExtensions.IsPunctionChar(Peek(queueOfCharsInStringToBeAdded)))
            {
                RemoveLastCharFromTextBlockAndReturnToQueue(queueOfCharsInStringToBeAdded, newTextBlockForOneLineOnly);
                AdjustmentsMade = true;
            }
            return AdjustmentsMade;
        }

        private static bool ReturnNumbersAfterPunctioationOrNumbersFromTextBlockToQueue(List<char> queueOfCharsInStringToBeAdded, TextBlock newTextBlockForOneLineOnly, bool AdjustmentsMade)
        {
            while (newTextBlockForOneLineOnly.Text.Length != 0
                   && ((NBiDiExtensions.IsNumberCharcter(GetLastCharInTextBlock(newTextBlockForOneLineOnly))
                        || NBiDiExtensions.IsPunctionChar(GetLastCharInTextBlock(newTextBlockForOneLineOnly))))
                   && NBiDiExtensions.IsNumberCharcter(Peek(queueOfCharsInStringToBeAdded)))
            {
                RemoveLastCharFromTextBlockAndReturnToQueue(queueOfCharsInStringToBeAdded, newTextBlockForOneLineOnly);
                AdjustmentsMade = true;
            }
            return AdjustmentsMade;
        }

        private static char GetLastCharInTextBlock(TextBlock newTextBlockForOneLineOnly)
        {
            return newTextBlockForOneLineOnly.Text[newTextBlockForOneLineOnly.Text.Length - 1];
        }

        private static void HandleWithBrokwnWords(TextBlock textBlockToRTL, List<char> queueOfCharsInStringToBeAdded, TextBlock newTextBlockForOneLineOnly)
        {
            if (textBlockToRTL.TextWrapping == TextWrapping.WrapWithOverflow)
            {
                GetAllBrokenWordToTextBlock(queueOfCharsInStringToBeAdded, newTextBlockForOneLineOnly);
            }
            else if (textBlockToRTL.TextWrapping == TextWrapping.Wrap)
            {
                ReturnAllBrokenWordsToQueue(queueOfCharsInStringToBeAdded, newTextBlockForOneLineOnly);
            }
        }

        private static bool GetrPunctioationAfterNumbersFromQueueToTextBlock(List<char> queueOfCharsInStringToBeAdded, TextBlock newTextBlockForOneLineOnly, bool AdjustmentsMade)
        {
            while (IsNotQueueEmpty(queueOfCharsInStringToBeAdded)
                   && NBiDiExtensions.IsNumberCharcter(GetLastCharInTextBlock(newTextBlockForOneLineOnly))
                   && NBiDiExtensions.IsPunctionChar(Peek(queueOfCharsInStringToBeAdded)))
            {
                newTextBlockForOneLineOnly.Text += GetFirstAndRemoveIt(queueOfCharsInStringToBeAdded);
                AdjustmentsMade = true;
            }
            return AdjustmentsMade;
        }

        private static bool GetNumbersAfterPunctioationOrNumbersFromQueueToTextBlock(List<char> queueOfCharsInStringToBeAdded, TextBlock newTextBlockForOneLineOnly, bool AdjustmentsMade)
        {
            while (IsNotQueueEmpty(queueOfCharsInStringToBeAdded)
                   && (NBiDiExtensions.IsNumberCharcter(GetLastCharInTextBlock(newTextBlockForOneLineOnly))
                       || NBiDiExtensions.IsPunctionChar(GetLastCharInTextBlock(newTextBlockForOneLineOnly)))
                   && NBiDiExtensions.IsNumberCharcter(Peek(queueOfCharsInStringToBeAdded)))
            {
                newTextBlockForOneLineOnly.Text += GetFirstAndRemoveIt(queueOfCharsInStringToBeAdded);
                AdjustmentsMade = true;
            }
            return AdjustmentsMade;
        }

        private static bool GetlAllSpacerFromQueueToTextBlock(List<char> queueOfCharsInStringToBeAdded, TextBlock newTextBlockForOneLineOnly, bool AdjustmentsMade)
        {
            while (IsNotQueueEmpty(queueOfCharsInStringToBeAdded)
                   && NBiDiExtensions.IsSpacerCharcter(Peek(queueOfCharsInStringToBeAdded)))
            {
                newTextBlockForOneLineOnly.Text += GetFirstAndRemoveIt(queueOfCharsInStringToBeAdded);
                AdjustmentsMade = true;
            }
            return AdjustmentsMade;
        }

        private static void GetAllBrokenWordToTextBlock(List<char> queueOfCharsInStringToBeAdded, TextBlock newTextBlockForOneLineOnly)
        {
            while ((IsNotQueueEmpty(queueOfCharsInStringToBeAdded)) &&
                   (!NBiDiExtensions.IsSpacerCharcter(Peek(queueOfCharsInStringToBeAdded))))
            {
                newTextBlockForOneLineOnly.Text +=
                    GetFirstAndRemoveIt(queueOfCharsInStringToBeAdded);
            }
        }

        private static void ReturnAllBrokenWordsToQueue(List<char> queueOfCharsInStringToBeAdded, TextBlock newTextBlockForOneLineOnly)
        {
            while ((newTextBlockForOneLineOnly.Text.Length != 0) &&
                   (!NBiDiExtensions.IsSpacerCharcter(GetLastCharInTextBlock(newTextBlockForOneLineOnly))))
            {
                RemoveLastCharFromTextBlockAndReturnToQueue(queueOfCharsInStringToBeAdded, newTextBlockForOneLineOnly);
            }
        }

        private static void RemoveLastCharFromTextBlockAndReturnToQueue(List<char> queueOfCharsInStringToBeAdded, TextBlock newTextBlockForOneLineOnly)
        {
            InsertAsFirst(queueOfCharsInStringToBeAdded, GetLastCharInTextBlock(newTextBlockForOneLineOnly));
            newTextBlockForOneLineOnly.Text = newTextBlockForOneLineOnly.Text.Remove(newTextBlockForOneLineOnly.Text.Length - 1, 1);
        }

        private static double AttachNewTextBlockAfterFinishedDeterminingItsText(TextBlock textBlockToRTL, Canvas ParentOfTextBlockToRTL, double curHeightOffsetForBreakLines, string curParagraph, double textBlockToRTLCanvasLeft, TextBlock newTextBlockForOneLineOnly, bool ForceAllParagraphsAsRTL, List<TextBlock> TextBlocksAttachedToCanvas, string lastLineText)
        {
            SetTextForTextBlockBasedOnIfNeedsRTLAndHasNonRTLLTRBegining(curParagraph, newTextBlockForOneLineOnly, lastLineText);
            newTextBlockForOneLineOnly.TextWrapping = TextWrapping.NoWrap;
            newTextBlockForOneLineOnly.Height = newTextBlockForOneLineOnly.ActualHeight;
            SetCanvasLeftForNewTextBlock(curParagraph, ForceAllParagraphsAsRTL, textBlockToRTL, textBlockToRTLCanvasLeft, newTextBlockForOneLineOnly);
            curHeightOffsetForBreakLines += newTextBlockForOneLineOnly.ActualHeight;
            ParentOfTextBlockToRTL.Children.Add(newTextBlockForOneLineOnly);
            TextBlocksAttachedToCanvas.Add(newTextBlockForOneLineOnly);
            return curHeightOffsetForBreakLines;
        }

        private static void SetTextForTextBlockBasedOnIfNeedsRTLAndHasNonRTLLTRBegining(string curParagraph, TextBlock newTextBlockForOneLineOnly, string lastLineText)
        {
            if (!NBiDiExtensions.IsTextNeedAlignToRight(curParagraph))
                newTextBlockForOneLineOnly.Text = NBidi.NBidi.LogicalToVisual(newTextBlockForOneLineOnly.Text);
            else
            {
                string TextNotToAlign;
                string textToBidi;
                CutTextNotToAlignBecauseOfStartAndCutTextToBiDi(newTextBlockForOneLineOnly, out TextNotToAlign, out textToBidi, lastLineText);

                newTextBlockForOneLineOnly.Text = NBidi.NBidi.LogicalToVisual(textToBidi) + TextNotToAlign;
            }
        }

        private static void CutTextNotToAlignBecauseOfStartAndCutTextToBiDi(TextBlock newTextBlockForOneLineOnly, out string TextNotToAlign, out string textToBidi, string lastLineText)
        {
            string textWithBadStart = RemoveFirstCharcter(newTextBlockForOneLineOnly.Text);
            int i;
            int j = -1;
            for (i = 0; i < textWithBadStart.Length; i++)
            {
                if (NBiDiExtensions.IsRTLChar(textWithBadStart[i])
                    || NBiDiExtensions.IsLTRChar(textWithBadStart[i]))
                {

                    break;
                }
            }
            if (i > 0)
                i--;

            //if (i != 0)
            for (j = i; j != -1; j--)
            {
                if (NBiDiExtensions.IsNumberCharcter(textWithBadStart[j]))
                {
                    break;
                }
            }
            if (j != -1)
                j++;

            // no need for pre-NBiDi cutting
            if (j == -1)
            {
                TextNotToAlign = string.Empty;
                textToBidi = newTextBlockForOneLineOnly.Text;
            }
            else
            {


                char firstChar = newTextBlockForOneLineOnly.Text[0];
                    
                    if (/*NBiDiExtensions.GetLTRorRTLStarterCharcterForLineFromLastCharToFirst(lastLineText).HasValue
                        && NBiDiExtensions.GetLTRorRTLStarterCharcterForLineFromLastCharToFirst(lastLineText).GetValueOrDefault()
                        && firstCharRemoved.HasValue
                        && firstCharRemoved.GetValueOrDefault() == NBiDiExtensions.RTLFirstCharMark*/
                        GetIndectionFromPreviousLine(lastLineText, firstChar) == NBiDiExtensions.RTLFirstCharMark)
                        TextNotToAlign = NBiDiExtensions.ReverseStringByWhiteSpaceForNumbersOnly(textWithBadStart.Substring(0, j));
                    else
                        TextNotToAlign = textWithBadStart.Substring(0, j);
                    
                    textToBidi = firstChar + textWithBadStart.Substring(j, textWithBadStart.Length - j);

            }
        }

        //private static void CutTextNotToAlignBecauseOfStartAndCutTextToBiDi(TextBlock newTextBlockForOneLineOnly, out string TextNotToAlign, out string rest, string lastLineText)
        //{
        //    string textWithBadStart = RemoveFirstCharcter(newTextBlockForOneLineOnly.Text);
        //    int i;
        //    int j = -1;
        //    for (i = 0; i < textWithBadStart.Length; i++)
        //    {
        //        if (NBiDiExtensions.IsRTLChar(textWithBadStart[i])
        //            || NBiDiExtensions.IsLTRChar(textWithBadStart[i]))
        //        {

        //            break;
        //        }
        //    }
        //    if (i > 0)
        //        i--;

        //    //if (i != 0)
        //    for (j = i; j != -1; j--)
        //    {
        //        if (NBiDiExtensions.IsNumberCharcter(textWithBadStart[j]))
        //        {
        //            break;
        //        }
        //    }
        //    if (j != -1)
        //        j++;

        //    // no need for pre-NBiDi cutting
        //    if (j == -1)
        //    {
        //        TextNotToAlign = string.Empty;
        //        rest = newTextBlockForOneLineOnly.Text;
        //    }
        //    else
        //    {
        //        char firstChar = newTextBlockForOneLineOnly.Text[0];

        //        char indectionFromPreviousLine = GetIndectionFromPreviousLine(lastLineText, firstChar);
        //        TextNotToAlign = NBidi.NBidi.LogicalToVisual(indectionFromPreviousLine + textWithBadStart.Substring(0, j));
        //        rest = firstChar + textWithBadStart.Substring(j, textWithBadStart.Length - j);
        //    }
        //}

        private static char GetIndectionFromPreviousLine(string lastLineText, char firstChar)
        {
            bool? isLastLineRTL = NBiDiExtensions.GetLTRorRTLStarterCharcterForLineFromLastCharToFirst(lastLineText);

            char indectionFromPreviousLine;
            if (isLastLineRTL.HasValue)
                indectionFromPreviousLine = NBiDiExtensions.GetLTRorRTLStarterCharcterForLine(isLastLineRTL.GetValueOrDefault());
            else
                indectionFromPreviousLine = firstChar;
            return indectionFromPreviousLine;
        }

        private static char? GetIndectionFromPreviousLine(string lastLineText)
        {
            bool? isLastLineRTL = NBiDiExtensions.GetLTRorRTLStarterCharcterForLineFromLastCharToFirst(lastLineText);

            char? indectionFromPreviousLine = null;
            if (isLastLineRTL.HasValue)
            {
                if (isLastLineRTL.GetValueOrDefault())
                    indectionFromPreviousLine = NBidi.BidiChars.RLE;
                else
                    indectionFromPreviousLine = NBidi.BidiChars.LRE;
            }
            
             //   indectionFromPreviousLine = NBiDiExtensions.GetLTRorRTLStarterCharcterForLine(isLastLineRTL.GetValueOrDefault());
            
           

            return indectionFromPreviousLine;
        }


        private static TextBlock InitlizeNewTextBlock(TextBlock textBlockToRTL, double curHeightOffsetForBreakLines, string curParagraph, double textBlockToRTLCanvasTop, List<char> queueOfCharsInStringToBeAdded, bool ForceAllParagraphsAsRTL, string lastLineText)
        {
            TextBlock newTextBlockForOneLineOnly = SilverlightExtensions.Clone(textBlockToRTL);
            newTextBlockForOneLineOnly.Text = GetFirstUnicodeRTLorLTRcharcter(textBlockToRTL, curParagraph, ForceAllParagraphsAsRTL, lastLineText).ToString();
            newTextBlockForOneLineOnly.SetValue(Canvas.TopProperty,
                                                textBlockToRTLCanvasTop +
                                                curHeightOffsetForBreakLines);
            newTextBlockForOneLineOnly.Text += GetFirstAndRemoveIt(queueOfCharsInStringToBeAdded);
            return newTextBlockForOneLineOnly;
        }

        private static void SetCanvasLeftForNewTextBlock(string curParagraph, bool ForceAllAsRTL, TextBlock textBlockToRTL, double textBlockToRTLCanvasLeft, TextBlock newTextBlockForOneLineOnly)
        {
            if (NBiDiExtensions.IsTextNeedAlignToRight(curParagraph) || ForceAllAsRTL)
            {
                double fixMove = textBlockToRTL.Width -
                                 newTextBlockForOneLineOnly.ActualWidth;
                double mirrorCanvasLeftForTextBlock = textBlockToRTLCanvasLeft + fixMove;
                newTextBlockForOneLineOnly.SetValue(Canvas.LeftProperty, mirrorCanvasLeftForTextBlock);

            }
            else
            {
                newTextBlockForOneLineOnly.SetValue(Canvas.LeftProperty, textBlockToRTLCanvasLeft);
            }
        }

        private static string GetFirstUnicodeRTLorLTRcharcter(TextBlock textBlockToRTL, string curParagraph, bool ForceALLAsRTL, string lastLineText)
        {
            char firstLTRorRTLCharForFirstLineInParagraph =
                NBiDiExtensions.GetLTRorRTLStarterCharcterForLine(
                    NBiDiExtensions.IsTextNeedAlignToRight(curParagraph) || ForceALLAsRTL);

            return firstLTRorRTLCharForFirstLineInParagraph.ToString();

            char? indectionFromPreviousSentence = GetIndectionFromPreviousLine(lastLineText);

            if (indectionFromPreviousSentence.HasValue
                && indectionFromPreviousSentence.GetValueOrDefault() != firstLTRorRTLCharForFirstLineInParagraph)
                return indectionFromPreviousSentence.GetValueOrDefault().ToString() + firstLTRorRTLCharForFirstLineInParagraph.ToString();
            else
                return firstLTRorRTLCharForFirstLineInParagraph.ToString();
        }

        private static char Peek(List<char> list)
        {
            return list[0];
        }

        private static void InsertAsFirst(List<char> list, char charToAdd)
        {
            list.Insert(0, charToAdd);
        }

        private static char GetFirstAndRemoveIt(List<char> list)
        {
            char ReturnValue = list[0];
            list.RemoveAt(0);
            return ReturnValue;
        }
    }
}